关于腐败:如何恢复因硬盘故障而损坏的Git对象?

您所在的位置:网站首页 git pack文件损坏 关于腐败:如何恢复因硬盘故障而损坏的Git对象?

关于腐败:如何恢复因硬盘故障而损坏的Git对象?

2024-07-09 09:39| 来源: 网络整理| 查看: 265

我的硬盘出现故障,导致Git存储库的一些文件损坏。当运行git fsck --full时,我得到以下输出:

1234567error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129 error: inflate: data stream error (invalid code lengths set) error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129 error: inflate: data stream error (invalid stored block lengths) error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted

我有存储库的备份,但只有包含pack文件的备份已损坏。所以我认为我必须找到一种方法从不同的备份中检索单个对象,并以某种方式指示Git生成一个只包含正确对象的新包。

你能给我提示一下如何修复我的存储库吗?

相关讨论 这件事发生在我身上。我不想搞砸Git对象…因此,将项目从远程存储库重新克隆到一个新文件夹中,然后只需复制问题存储库中的所有文件(当然不包括.git文件夹)到新克隆的报告中…然后,在新的回购协议中,git status…Git正确地检测到所有受影响的文件更改,我可以重新开始工作。

在以前的一些备份中,坏对象可能打包在不同的文件中,或者可能是松散对象。因此,您的对象可能会被恢复。

数据库中似乎有一些坏对象。所以你可以用手工的方法。

由于git hash-object,git mktree和git commit-tree不写对象,因为它们在包中被发现,然后开始这样做:

12345mv .git/objects/pack/* for i in /*.pack; do   git unpack-objects -r < $i done rm /*

(您的包将从存储库中移出,并再次在其中解包;只有好的对象现在在数据库中)

你可以这样做:

1git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

并检查对象的类型。

如果类型为blob:从以前的备份(使用git show或git cat-file或git unpack-file检索文件的内容;那么可以使用git hash-object -w重写当前存储库中的对象。

如果类型为tree:可以使用git ls-tree从以前的备份中恢复树;然后使用git mktree在当前存储库中再次写入。

如果类型为commit,则与git show、git cat-file和git commit-tree相同。

当然,在开始这个过程之前,我会备份您的原始工作副本。

另外,看看如何恢复损坏的blob对象。

相关讨论 谢谢你,救了我!我将把我的准确步骤作为一个单独的答案贴出来。 只是更正一下:命令的结尾是"完成",而不是"结束"。 我想这么做,但.git/objects/pack/是空的 对我来说,在Git解包对象-r @密特拉迪尔:如果你把"完成"放在前一行:是的,你需要一个分号。如果你准确地输入我写的,你不会。 我面临着这个问题:stackoverflow.com/q/38770736/575643我尝试过你的解决方案,但没能解决这个问题,你知道如何解决这个问题吗?

班纳格斯让我走上了正轨。为了进一步参考,我想发布我为修复我的存储库损坏所采取的步骤。我很幸运能在旧包或存储库备份中找到所有需要的对象。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051# Unpack last non-corrupted pack $ mv .git/objects/pack .git/objects/pack.old $ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack $ git log fatal: bad object HEAD $ cat .git/HEAD ref: refs/heads/master $ ls .git/refs/heads/ $ cat .git/packed-refs # pack-refs with: peeled aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master $ git fsck --full error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1 error: refs/heads/master does not point to a valid object! missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919 missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc # Copy HEAD object from backup of repository $ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa # Now copy all missing objects from backup of repository and run"git fsck --full" afterwards # Repeat until git fsck --full only reports dangling objects # Now garbage collect repo $ git gc warning: reflog of 'HEAD' references pruned commits warning: reflog of 'refs/heads/master' references pruned commits Counting objects: 3992, done. Delta compression using 2 threads. fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232) error: failed to run repack # Check reflogs... $ git reflog # ...then clean $ git reflog expire --expire=0 --all # Now garbage collect again $ git gc       Counting objects: 3992, done. Delta compression using 2 threads. Compressing objects: 100% (3970/3970), done. Writing objects: 100% (3992/3992), done. Total 3992 (delta 2060), reused 0 (delta 0) Removing duplicate objects: 100% (256/256), done. # Done! 相关讨论 补充:如果备份包中有丢失的文件,从包中获取blob的正确方法是"git cat file blob>file.dat",并且要将其恢复到损坏的repo中,请执行"git hash object-w file.dat",如Daniel的回答中所示。 如何找到最后一个未损坏的包?谢谢

首先尝试以下命令(如果需要,请重新运行):

12345$ git fsck --full $ git gc $ git gc --prune=today $ git fetch --all $ git pull --rebase

然后你仍然有问题,可以尝试:

移除所有损坏的对象,例如

12fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt $ rm -v .git/objects/06/91c5...51e5

移除所有空对象,例如

12error: object file .git/objects/06/91c5...51e5 is empty $ find .git/objects/ -size 0 -exec rm -vf"{}" \;

通过以下方式检查"断开的链接"消息:

1git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8

这将告诉您损坏的blob来自哪个文件!

要恢复文件,您可能真的很幸运,它可能是您已经在工作树中签出的版本:

1git hash-object -w my-magic-file

再一次,如果它输出丢失的sha1(4b945….),你现在都完成了!

假设是某个旧版本被破坏,最简单的方法是:

1git log --raw --all --full-history -- subdirectory/my-magic-file

这将显示该文件的整个日志(请注意,您所拥有的树可能不是顶级树,因此您需要自己确定它在哪个子目录中),然后您现在可以用哈希对象重新创建丢失的对象。

要获取所有缺少提交、树或blob的引用的列表,请执行以下操作:

1$ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo"in $ref"; done

可能无法使用常规的branch-d或tag-d命令删除其中的一些ref,因为如果git注意到损坏,它们将死亡。所以使用管道命令git update ref-d$ref代替。注意,对于本地分支,此命令可能会将过时的分支配置留在.git/config中。可以手动删除(请查找[分支"$ref"]部分)。

在所有引用都清除之后,reflog中可能仍有断开的提交。您可以使用git reflog expire--expire=now--all清除所有重新登录。如果您不想丢失所有的反射,可以搜索单个反射以查找断开的反射:

1$ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo"in $ref"; done

(注意在git rev列表中添加了-g选项。)然后,使用git reflog expire--expire=now$ref。当所有断开的ref和reflogs都消失后,运行git fsck--full以检查存储库是否干净。悬挂物体正常。

下面您可以找到命令的高级用法,如果使用不当,这些命令可能会导致您的Git存储库中的数据丢失,因此请在意外对Git造成进一步损坏之前进行备份。如果你知道自己在做什么,就要冒险。

提取后,要将当前分支拉到上游分支的顶部,请执行以下操作:

1$ git pull --rebase

您还可以尝试签出新分支并删除旧分支:

1$ git checkout -b new_master origin/master

要在Git中查找要删除的损坏对象,请尝试以下命令:

1while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f"$f" ]; then break; fi; echo delete $f; rm -f"$f"; done

对于OSX,使用sed -E而不是sed -r。

另一种方法是从pack文件中解包所有对象,以重新生成.git/对象中的所有对象,因此尝试在存储库中运行以下命令:

123$ cp -fr .git/objects/pack .git/objects/pack.bak $ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done $ rm -frv .git/objects/pack.bak

如果上面没有帮助,您可以尝试从另一个repo同步或复制git对象,例如。

123$ rsync -varu git_server:/path/to/git/.git local_git_repo/ $ rsync -varu /local/path/to/other-working/git/.git local_git_repo/ $ cp -frv ../other_repo/.git/objects .git/objects

要在尝试签出时修复断开的分支,请执行以下操作:

12$ git checkout -f master fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625

尝试将其移除并再次从上游签出:

12$ git branch -D master $ git checkout -b master github/master

如果Git使您进入分离状态,请签出master并合并到分离的分支中。

另一个想法是递归地重新设置现有主控形状:

12$ git reset HEAD --hard $ git rebase -s recursive -X theirs origin/master

另请参见:

为了修复损坏的存储库而重建blob对象的一些技巧。 如何修复损坏的存储库? 如何从存储库中删除所有断开的引用? 如何修复损坏的Git存储库?(请参见) 如何修复损坏的Git存储库?(双鼓) 将sourcetree与git一起使用时出错:"summary"失败,代码128:致命:无法读取树 恢复损坏的Git裸机存储库 恢复损坏的Git存储库 如何修复Git错误:对象是Empy/已损坏 如何诊断和修复git致命:无法读取树 如何处理这个Git错误 如何修复损坏的Git存储库? 如何"覆盖"而不是"合并",Git中另一个分支上的分支? 如何从另一个分支完全替换Git中的主分支? git:"损坏的松散对象" git reset=致命:无法读取树

以下是我从损坏的blob对象中恢复的步骤。

1)识别损坏的blob

12345git fsck --full   error: inflate: data stream error (incorrect data check)   error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd   error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing   ...

损坏的blob是241091723C324AED77B2D35F97A05E856B319 EFD

2)将损坏的blob移到安全的地方(以防万一)

1mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/

3)获取损坏blob的父级

12345git fsck --full   Checking object directories: 100% (256/256), done.   Checking objects: 100% (70321/70321), done.   broken link from    tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180               to    blob 241091723c324aed77b2d35f97a05e856b319efd

父哈希为0716831E1A6C8D3E6B2B541D21C4748CC0CE7180。

4)获取与损坏blob对应的文件名

1234git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180   ...   100644 blob 241091723c324aed77b2d35f97a05e856b319efd    dump.tar.gz   ...

在备份或上游Git存储库中找到这个特定的文件(在我的例子中是dump.tar.gz)。然后将其复制到本地存储库中的某个位置。

5)在git对象数据库中添加以前损坏的文件

1git hash-object -w dump.tar.gz

6)庆祝!

12345git gc   Counting objects: 75197, done.   Compressing objects: 100% (21805/21805), done.   Writing objects: 100% (75197/75197), done.   Total 75197 (delta 52999), reused 69857 (delta 49296)

相关讨论 这对我不起作用。步骤4产生了git ls-tree 9504a07fb803edfdf0c1dd99c5d561274af87982 error: Could not read 19505205fd1f219993da9b75846fff3cf432152d,我也在没有步骤2的情况下重新尝试了一遍,结果产生了git ls-tree 9504a07fb803edfdf0c1dd99c5d561274af87982 error: inflate: data stream error (invalid stored block lengths) fatal: failed to read object 19505205fd1f219993da9b75846fff3cf432152d: Invalid argument。

如果备份已损坏,或者您也有一些部分损坏的备份(如果备份损坏的对象,可能会发生这种情况),以下两个功能可能会有所帮助。

在你试图恢复的回购协议中运行两者。

标准警告:只有当您真的非常绝望并且备份了(损坏的)回购时才使用。这可能无法解决任何问题,但至少应该突出腐败的程度。

123456789101112131415161718192021fsck_rm_corrupted() {     corrupted='a'     while ["$corrupted" ]; do         corrupted=$(                                  \         git fsck --full --no-dangling 2>&1 >/dev/null \             | grep 'stored in'                          \             | sed -r 's:.*(\.git/.*)\).*:\1:'           \         )         echo"$corrupted"         rm -f"$corrupted"     done } if [ -z"$1" ]  || [ ! -d"$1" ]; then     echo"'$1' is not a directory. Please provide the directory of the git repo"     exit 1 fi pushd"$1">/dev/null fsck_rm_corrupted popd >/dev/null

12345678910111213141516171819202122unpack_rm_corrupted() {     corrupted='a'     while ["$corrupted" ]; do         corrupted=$(                                  \         git unpack-objects -r &1 >/dev/null \             | grep 'stored in'                          \             | sed -r 's:.*(\.git/.*)\).*:\1:'           \         )         echo"$corrupted"         rm -f"$corrupted"     done } if [ -z"$1" ]  || [ ! -d"$1" ]; then     echo"'$1' is not a directory. Please provide the directory of the git repo"     exit 1 fi for p in $1/objects/pack/pack-*.pack; do     echo"$p"     unpack_rm_corrupted"$p" done

Git签出实际上可以从版本中选择单个文件。只需给它提交哈希和文件名。这里有更详细的信息。

我想最简单的安全修复方法是恢复到最新的未受限制的备份,然后有选择地从较新的提交中选择未损坏的文件。祝你好运!

我已经解决了这个问题,添加了一些更改,比如git-add-a和git-commit。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3